 using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Infrastructure;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Text;
using System.Web.Script.Serialization;


namespace WCFObserver
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    // NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
     [ServiceBehavior(IncludeExceptionDetailInFaults = true,
        InstanceContextMode = InstanceContextMode.Single)]
    public class Service1 : IWCFObserver
    {
        List<IWcfObserverClientFeed> subscribersList = new List<IWcfObserverClientFeed>();

        public void Subscribe()
        {
            var wcfClientFeed = OperationContext.Current.GetCallbackChannel<IWcfObserverClientFeed>();
            if (!subscribersList.Contains(wcfClientFeed))
            {
                subscribersList.Add(wcfClientFeed);
            }
        }

        public void Unsubscribe()
        {
            var wcfClientCallback = OperationContext.Current.GetCallbackChannel<IWcfObserverClientFeed>();
            if (subscribersList.Contains(wcfClientCallback))
            {
                subscribersList.Remove(wcfClientCallback);
            }
        }

        public void OnCompleted()
        {
            Action(s => s.OnCompleted());
        }

        public void OnError(Exception error)
        {
            Action(s => s.OnError(error));
        }

        public void OnNext(EventType value)
        {
            Action(s => s.OnNext(value));
        }

        void Action(Action<IWcfObserverClientFeed> call)
        {
            var disconnected = subscribersList.Where(s =>
            {
                try
                {
                    call(s);
                    return false;
                }
                catch (ObjectDisposedException)
                {
                    Console.WriteLine("Connection already disposed, disconnecting client's channel");
                    return true;
                }
            }
            );
            disconnected.ToList().ForEach(s => subscribersList.Remove(s));
        }
    }

    public class WcfObserver : IObserver<EventType>
    {
        
        Service1 _observerService;
        

        public WcfObserver()
        {
            _observerService = new Service1();
            
        }

        public void OnCompleted()
        {
            Console.WriteLine("Wcf Observer OnCompleted");
            _observerService.OnCompleted();
        }

        public void OnError(Exception error)
        {
            Console.WriteLine("Wcf Observer OnError: " + error.Message);
            _observerService.OnError(error);
        }

        public void OnNext(EventType value)
        {
            //var json = new JavaScriptSerializer().Serialize(value);
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<theHub>();
            //context.Clients.All.receive(json);
            context.Clients.All.receive(value);
            Console.WriteLine("sent ");
            _observerService.OnNext(value);
        }
    
    }
}
